/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.neo4j.cypher.internal.util.helpers

import org.neo4j.cypher.internal.util.helpers.NameDeduplicator.removeGeneratedNamesAndParams
import org.neo4j.cypher.internal.util.helpers.NameDeduplicator.removeGeneratedNamesAndParamsOnTree
import org.neo4j.cypher.internal.util.test_helpers.CypherFunSuite

class NameDeduplicatorTest extends CypherFunSuite {

  private case class Foo(s: String)

  test("should remove simple numbered variable names") {
    removeGeneratedNamesAndParams("  var@33") should equal("var")
  }

  test("should reformat autogenerated variables names") {
    removeGeneratedNamesAndParams("  UNNAMED42") should equal("anon_42")
  }

  test("should reformat autogenerated variables names with negative number") {
    removeGeneratedNamesAndParams("  UNNAMED-42") should equal("anon_-42")
  }

  test("should reformat autogenerated param names") {
    removeGeneratedNamesAndParams("  AUTOINT33") should equal("autoint_33")
  }

  test("should remove nested numbered variable names") {
    removeGeneratedNamesAndParams("    var@33@36") should equal("var")
  }

  test("should rewrite Strings in trees") {
    removeGeneratedNamesAndParamsOnTree(Foo("  var@33")) should equal(Foo("var"))
  }

  test("should remove names with complex expressions before the @") {
    removeGeneratedNamesAndParams("  n.prop@33") should equal("n.prop")
    removeGeneratedNamesAndParams("  n.prop + 5@33") should equal("n.prop + 5")
  }

  test("should remove names multiple times in longer strings") {
    removeGeneratedNamesAndParams(
      "SHORTEST 1 ((u) ((  n@0)-[  r@1]->(  m@2)){1, } (v)-[r2]->(w) WHERE NOT r2 IN `  r@4` AND unique(`  r@4`) AND v{foo: v.foo, bar: v.bar} = w{foo: w.foo, bar: w.bar})"
    ) should equal(
      "SHORTEST 1 ((u) ((n)-[r]->(m)){1, } (v)-[r2]->(w) WHERE NOT r2 IN `r` AND unique(`r`) AND v{foo: v.foo, bar: v.bar} = w{foo: w.foo, bar: w.bar})"
    )
    removeGeneratedNamesAndParams(
      "SHORTEST 1 ((u) ((  a@2)-[  r@3]->(  b@4)){1, } (v)-[s]->(w) WHERE EXISTS { MATCH (v)-[`  UNNAMED0`]->(`  UNNAMED1`)\n  WHERE `  UNNAMED1`:N } AND NOT s IN `  r@6` AND unique(`  r@6`))"
    ) should equal(
      "SHORTEST 1 ((u) ((a)-[r]->(b)){1, } (v)-[s]->(w) WHERE EXISTS { MATCH (v)-[`anon_0`]->(`anon_1`)\n  WHERE `anon_1`:N } AND NOT s IN `r` AND unique(`r`))"
    )
  }
}
